#include "do_co2.h"
#include "do_pm25.h"
#include "http_server.h"
#include "socket.h"
#include "w55mh32_wztoe.h"
#include "web_page.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#if LOOPBACK_MODE == LOOPBACK_MAIN_NOBLCOK

// 定义请求行结构体
typedef struct {
  char method[16];  // 如 "GET"
  char uri[256];    // 如 "/"
  char version[16]; // 如 "HTTP/1.1"
} http_request_line;

// 解析请求行函数
int parse_request_line(const char *request, http_request_line *req_line) {
  char buffer[1024];
  strncpy(buffer, request, sizeof(buffer));
  buffer[sizeof(buffer) - 1] = '\0'; // 确保终止

  // 找到第一行末尾（\r\n）
  char *line_end = strstr(buffer, "\r\n");
  if (!line_end) {
    return -1; // 格式错误
  }
  *line_end = '\0'; // 截断为单行

  // 用 strtok 分割方法、URI、版本
  char *method = strtok(buffer, " ");
  char *uri = strtok(NULL, " ");
  char *version = strtok(NULL, " ");

  if (!method || !uri || !version) {
    return -1;
  }

  // 存入结构体
  strncpy(req_line->method, method, sizeof(req_line->method) - 1);
  strncpy(req_line->uri, uri, sizeof(req_line->uri) - 1);
  strncpy(req_line->version, version, sizeof(req_line->version) - 1);

  return 0; // 成功
}

/**
 * @brief   tcp server loopback test
 * @param   sn:    socket number
 * @param   buf:   Data sending and receiving cache
 * @param   port:  Listen port
 * @return  value for SOCK_ERRORs,return 1:no error
 */
int32_t loopback_tcps(uint8_t sn, uint8_t *buf, uint16_t port) {
  int32_t ret = 0;
  uint16_t size = 0;
  uint16_t sentsize = 0;

  switch (getSn_SR(sn)) {
  case SOCK_ESTABLISHED:
    if (getSn_IR(sn) & Sn_IR_CON) {

      setSn_IR(sn, Sn_IR_CON);
    }
    if ((size = getSn_RX_RSR(sn)) >
        0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
    {
      if (size > DATA_BUF_SIZE) {
        size = DATA_BUF_SIZE;
      }
      ret = recv(sn, buf, size);

      if (ret <= 0) {
        return ret; // check SOCKERR_BUSY & SOCKERR_XXX. For showing the
      }
      // occurrence of SOCKERR_BUSY.
      size = (uint16_t)ret;
      sentsize = 0;
      buf[size] = 0x00;
      printf("rece data:%s\r\n", buf);

      http_request_line req_line;
      if (parse_request_line((char *)buf, &req_line) == 0) {
        printf("Method: %s\n", req_line.method);   // 输出: GET
        printf("URI: %s\n", req_line.uri);         // 输出: /
        printf("Version: %s\n", req_line.version); // 输出: HTTP/1.1

        if (strcmp(req_line.method, "GET") == 0 &&
            strcmp(req_line.uri, "/") == 0) {
          char html_buffer[2048]; // 确保缓冲区足够大
          // 使用实际数据填充HTML模板
          snprintf(html_buffer, sizeof(html_buffer), INDEX_PAGE,
                   g_co2_concentration, g_pm25_concentration);

          uint16_t content_len = strlen(html_buffer);
          sentsize = 0;
          while (content_len != sentsize) {
            ret = send(sn, (uint8_t *)html_buffer + sentsize,
                       content_len - sentsize);
            if (ret < 0) {
              close(sn);
              return ret;
            }
            sentsize += ret;
          }
          disconnect(sn);
          close(sn);
        } else if (strcmp(req_line.method, "GET") == 0 &&
                   strcmp(req_line.uri, "/api/sensor") == 0) {
          char sensor_data[64];

          sprintf(sensor_data, "{\"pm25\":%u,\"co2\":%u}", g_co2_concentration,
                  g_pm25_concentration);
          char response[128];
          sprintf(response,
                  "HTTP/1.1 200 OK\r\n"
                  "Content-Type: application/json\r\n"
                  "Connection: close\r\n"
                  "\r\n"
                  "%s",
                  sensor_data);
          send(sn, (uint8_t *)response, strlen(response));
          disconnect(sn);
          close(sn);
        } else {
          send(sn, (uint8_t *)HTTP_RESPONSE_404, strlen(HTTP_RESPONSE_404));
          disconnect(sn);
          close(sn);
        }
      }

      else {
        printf("解析失败！\n");
      }
    }
    break;
  case SOCK_CLOSE_WAIT:
    if ((ret = disconnect(sn)) != SOCK_OK) {
      return ret;
    }
    break;
  case SOCK_INIT:
    if ((ret = listen(sn)) != SOCK_OK) {
      return ret;
    }
    break;
  case SOCK_CLOSED:
    if ((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) {
      return ret;
    }
    break;
  default:
    break;
  }
  return 1;
}

int32_t loopback_udpc(uint8_t sn, uint8_t *buf, uint8_t *destip,
                      uint16_t destport) {
  int32_t ret = 0;
  uint16_t size = 0;
  uint16_t sentsize = 0;
  static uint16_t s_any_port = 50000;

  switch (getSn_SR(sn)) {
  case SOCK_UDP:

    if ((size = getSn_RX_RSR(sn)) > 0) {
      if (size > DATA_BUF_SIZE) {
        size = DATA_BUF_SIZE;
      }
      ret = recvfrom(sn, buf, size, destip, (&destport));
      buf[ret] = 0x00;
      printf("recv form[%d.%d.%d.%d][%d]: %s\r\n", destip[0], destip[1],
             destip[2], destip[3], destport, buf);
      if (ret <= 0) {
#ifdef _LOOPBACK_DEBUG_
        printf("%d: recvfrom error. %ld\r\n", sn, ret);
#endif
        return ret;
      }
      size = (uint16_t)ret;
      sentsize = 0;
      while (sentsize != size) {
        ret = sendto(sn, buf + sentsize, size - sentsize, destip, destport);
        if (ret < 0) {
#ifdef _LOOPBACK_DEBUG_
          printf("%d: sendto error. %ld\r\n", sn, ret);
#endif
          return ret;
        }
        sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
      }
    }
    break;
  case SOCK_CLOSED:
#ifdef _LOOPBACK_DEBUG_
    // printf("%d:UDP loopback start\r\n",sn);
#endif
    if ((ret = socket(sn, Sn_MR_UDP, s_any_port, 0x00)) != sn) {
      return ret;
    }
#ifdef _LOOPBACK_DEBUG_
    printf("%d:Opened, UDP loopback, port [%d]\r\n", sn, s_any_port);
#endif
    break;
  default:
    break;
  }
  return 1;
}
#endif
